((expr)=>{
    expr.local={
        set(key,val){
            let obj={};
            obj[key]=val;
            return new Promise((res,rej)=>{
                chrome.storage.local.set(obj, res);
            })
        },
        get(key){
            return new Promise((res,rej)=>{
                chrome.storage.local.get(key, (obj)=>{
                    res(obj[key]);
                });
            })
        },
        remove(key){
            return new Promise((res,rej)=>{
                chrome.storage.local.remove(key, res);
            })
        },
        clear(){
            return new Promise((res,rej)=>{
                chrome.storage.local.clear(res);
            })
        }
    };
    expr.download=function(filename, text) {
        let element = document.createElement('a');
        element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
        element.setAttribute('download', filename);
        element.style.display = 'none';
        document.body.appendChild(element);
        element.click();
        document.body.removeChild(element);
    };
    expr.responseHeader=function(){
        let headerList=[];

        /* 监听response headers接收事件*/
        chrome.webRequest.onHeadersReceived.addListener(function(details) {
            let headers = details.responseHeaders;
            for (let obj of headerList){
                if(details.url.includes(obj.url)){
                    if(obj.headerVal && headers.filter(x=>x.name.toLocaleLowerCase() === obj.headerKey.toLocaleLowerCase()).length<1){
                        headers.push({
                            name:obj.headerKey,
                            value:obj.headerVal
                        })
                    }else{
                        for (let i = 0; i < headers.length; ++i) {
                            // 移除X-Frame-Options字段
                            if (headers[i].name.toLocaleLowerCase() === obj.headerKey.toLocaleLowerCase()) {
                                if(obj.headerVal){
                                    headers[i].value=obj.headerVal;
                                }else{
                                    headers.splice(i, 1);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            // 返回修改后的headers列表
            return { responseHeaders: headers };
        }, {
            urls: ["<all_urls>"]
        }, ["extraHeaders","blocking", "responseHeaders"]);

        return {
            add(url,headerKey,headerVal){
                if(url && headerKey){
                    headerList.push({url,headerKey,headerVal})
                }
            },
            rm(url,headerKey){
                headerList.forEach((obj,i)=>{
                    if(obj.url===url && headerKey===headerKey){
                        headerList.splice(i,1);
                        return false;
                    }
                })
            }
        };
    };
    expr.requestHeader=function(){
        let headerList=[];
        /* 监听response headers接收事件*/
        chrome.webRequest.onBeforeSendHeaders.addListener(function(details) {
            let headers = details.requestHeaders;
            for (let obj of headerList){
                if(details.url.includes(obj.url)){
                    if(obj.headerVal && headers.filter(x=>x.name.toLocaleLowerCase() === obj.headerKey.toLocaleLowerCase()).length<1){
                        headers.push({
                            name:obj.headerKey,
                            value:obj.headerVal
                        })
                    }else{
                        for (let i = 0; i < headers.length; ++i) {
                            // 移除X-Frame-Options字段
                            if (headers[i].name.toLocaleLowerCase() === obj.headerKey.toLocaleLowerCase()) {
                                if(obj.headerVal){
                                    headers[i].value=obj.headerVal;
                                }else{
                                    headers.splice(i, 1);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            // 返回修改后的headers列表
            return { requestHeaders: headers };
        }, {
            urls: ["<all_urls>"]
        }, ["extraHeaders","blocking", "requestHeaders"]);

        return {
            add(url,headerKey,headerVal){
                if(url && headerKey){
                    headerList.push({url,headerKey,headerVal})
                }
            },
            rm(url,headerKey){
                headerList.forEach((obj,i)=>{
                    if(obj.url===url && headerKey===headerKey){
                        headerList.splice(i,1);
                        return false;
                    }
                })
            }
        };
    };
    expr.redirectLink=function(){
        let urls=[];
        /* 监听response headers接收事件*/
        chrome.webRequest.onBeforeRequest.addListener(function(details) {
            for (let obj of urls){
                if(new RegExp(obj.url,'ig').test(details.url) && obj.redirectUrl){
                    //直接重定向
                    return { redirectUrl: obj.redirectUrl};
                }
            }
        }, {
            urls: ["<all_urls>"]
        }, ["blocking"]);

        return {
            add(url,redirectUrl){
                if(url && redirectUrl){
                    urls.push({url,redirectUrl:redirectUrl,$redirectUrl:redirectUrl})
                }
            },
            rm(url){
                urls.forEach((obj,i)=>{
                    if(obj.url===url ){
                        urls.splice(i,1);
                        return false;
                    }
                })
            }
        };
    };
    expr.UrlFormate=function (url) {
        url=new URL(url);
        let params={};
        //处理vue的
        if(url.hash[0]==='#'){
            url.hashPath=url.hash.substring(1,url.hash.indexOf('?'));
            url.hashPathList=expr.DecodeHashPath(url.hashPath);
            let list=expr.DecodePar(url.hash.substring(url.hash.indexOf('?')+1));
            Object.keys(list).forEach((key)=>{
                url.searchParams.set(key,list[key]);
            })
        }
        for (let p of url.searchParams) {
            let data=decodeURIComponent(p[1]||'');
            try{
                data=JSON.parse(data)
            }catch (e) {

            }
            params[p[0]]=data;
        }
        url.params=params;
        url.pathList=expr.DecodeHashPath(url.pathname);
        return url;
    };
    expr.DecodePar=function(url) {
        try{
            return JSON.parse(url);
        }catch (e) {

        }
        url=url.split('&');
        let params={};
        for (let p of url) {
            let par=p.split('=');
            if(par && par.length>1){
                let data=decodeURIComponent(par[1]||'');
                try{
                    data=JSON.parse(data)
                }catch (e) {

                }
                params[par[0]]=data;
            }
        }

        return params;
    };
    expr.EncodePar=function(obj) {
        if(typeof obj==='object'){
            let ret=null;
            for(let key of Object.keys(obj)){
                if(!ret){
                    ret=key+'='+encodeURIComponent(obj[key]);
                }else{
                    ret+='&'+key+'='+encodeURIComponent(obj[key]);
                }
            }
            return ret;
        }
        return obj;
    };
    expr.DecodeHashPath=function (str) {
        if(!str)return str;
        return str.split('/');
    };
    expr.EncodeHashPath=function (list) {
        return list.join('/');
    };
    expr.fireKeyEvent=function(el, evtType, keyCode) {
        if(typeof el==='string'){
            el=document.querySelector(el);
        }
        let evtObj;
        if (document.createEvent) {
            if (window.KeyEvent) {//firefox 浏览器下模拟事件
                evtObj = document.createEvent('KeyEvents');
                evtObj.initKeyEvent(evtType, true, true, window, true, false, false, false, keyCode, 0);
            } else {//chrome 浏览器下模拟事件
                evtObj = document.createEvent('UIEvents');
                evtObj.initUIEvent(evtType, true, true, window, 1);

                delete evtObj.keyCode;
                if (typeof evtObj.keyCode === "undefined") {//为了模拟keycode
                    Object.defineProperty(evtObj, "keyCode", { value: keyCode });
                } else {
                    evtObj.key = String.fromCharCode(keyCode);
                }

                if (typeof evtObj.ctrlKey === 'undefined') {//为了模拟ctrl键
                    Object.defineProperty(evtObj, "ctrlKey", { value: true });
                } else {
                    evtObj.ctrlKey = true;
                }
            }
            el.dispatchEvent(evtObj);

        } else if (document.createEventObject) {//IE 浏览器下模拟事件
            evtObj = document.createEventObject();
            evtObj.keyCode = keyCode
            el.fireEvent('on' + evtType, evtObj);
        }
    }
})(window);
/*
console.clear();
console.log(decodeURIComponent(atob('JTI1YyVFNiU5QyVBQyVFNiU4RiU5MiVFNCVCQiVCNiVFNyU5NCVCMSVFNiU5OCU5MyVFNiU5NCVBRiVFNyU4MyU5RiVFNiU4RiU5MCVFNCVCRSU5QiVFNiU4QSU4MCVFNiU5QyVBRiVFNiU5NCVBRiVFNiU4QyU4MSUyNWNRUTQ2NDMxMjQwNg==')),'background:#056bad;font-size:8px;padding:4px 8px;color:#ffffff;border-radius:4px 0 0 4px;','background:red;font-size:8px;padding:4px 8px;color:#ffffff;border-radius:0 4px 4px 0;');
console.log(decodeURIComponent(atob('JTI1Y2Jsb2clRUYlQkMlOUElMjVjaHR0cHMlM0ElMkYlMkZibG9nLjF6eWFuLmNu')),'color:red','');*/
